package com.example.demo.sf;

import java.util.Iterator;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * 单链表
 */
public  class SignalLinkedList implements Iterable<Integer>{

    private Node head;

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            Node cur = head;
            //  表示是否消耗下一个节点
            @Override
            public boolean hasNext() {
                // 判断当前节点是否为null,如果不是null 就返回true
                return null != cur;
            }

            @Override
            public Integer next() {
                // 返回当前节点的值, 并移动到下一个节点
                Integer value = cur.value;
                cur = cur.next;
                return value;
            }
        };
    }

    /**
     * 这里静态内部类主要是为了对外隐藏节点类
     * 复习一个知识点
     * 为什么要用static 关键字   什么时候内部类加载static 什么时候不用
     * 当内部类不依赖外部类的成员变量的时候，内部类可以加static关键字
     *
     */
    private static class Node {
        private int value;
        private Node next;

        public Node() {
        }

        public Node(int value, Node next) {
            this.value = value;
            this.next = next;
        }
    }
    /**
     * 按照索引删除指定的节点
     */
    public void remove(int index) {
        if (head == null) {
            return;
        }
        if (index == 0) {
            head = head.next;
            return;
        }
        // 找到前一个节点
        Node pre = getNode(index - 1);
        if (null == pre) {
            return;
        }
        // 找到当前要被删除的节点
        Node cur = pre.next;
        if(null == cur){
            return;
        }
        pre.next = cur.next;
    }


    /**
     * 删除最后一个节点
     */
    public void removeLast() {
        if (head == null) {
            return;
        }
        if (head.next == null) {
            head = null;
            return;
        }
        Node pre = head;
        while (pre.next.next != null) {
            pre = pre.next;
        }
        pre.next = null;
    }

    /**
     * 删除第一个节点
     */
    public void removeFirst() {
        if (head == null) {
            return;
        }
        head = head.next;
    }

    /**
     *
     * for循环遍历链表
     */
    public void display2(Consumer<Integer> consumer) {
        for (Node cur = head; cur != null; cur = cur.next){
            consumer.accept(cur.value);
        }
    }

    /**
     * 遍历链表
     * 从head开始遍历 一直到null
     */
    public void display(Consumer<Integer> consumer) {
        Node cur = head;
        while (cur != null) {
            consumer.accept(cur.value);
            cur = cur.next;
        }
    }

    /**
     * 头插法
     * 在头部插入一个元素
     * @param value
     */
    public void addFirst(int value) {
        /**
         * 创建一个新节点，将新节点的next指向head
         * 将head指向新节点
         * 如果这个链表是空的，那么head节点指向的就是null
         * 添加一个元素之后，head节点就是指向新插入的节点，新节点的next节点就是原有的head节点指向的节点
         */
        head = new Node(value, head);
    }
    /**
     * 尾插法
     * 在链表尾部插入一个元素
     * @param value
     */
    public void addLast(int value) {
        Node node = new Node(value, null);
        if (head == null) {
            head = node;
        } else {
            Node cur = head;
            while (cur.next != null) {
                cur = cur.next;
            }
            cur.next = node;
        }
    }
    /**
     * 在指定索引位置插入元素
     */
    public void add(int index, int value) {
        if (index == 0) {
            addFirst(value);
            return;
        }
        // 找到上一个节点
        Node node = getNode(index -1);
        Optional.ofNullable(node).orElseThrow(()->new IndexOutOfBoundsException("数组越界"));
        node.next = new Node(value, node.next);
    }

    /**
     * 展示索引值
     */
    public void displayIndex() {
        int i =0 ;
        for (Node cur = head; cur != null; cur = cur.next,i++){
            System.out.println( "当前值是:"+cur.value+",索引是:"+i);
        }
    }
    /**
     * 根据索引查询节点元素
     * */
    private Node getNode(int index) {
        int i = 0;
        for (Node cur = head; cur != null; cur = cur.next,i++){
            if (i == index) {
                return cur;
            }
        }
        return null;
    }

    /**
     * 根据索引获取元素的值
     */
    public int get(int index) {
        Node node = getNode(index);
        return Optional.ofNullable(node).map(cur ->  cur.value).orElseThrow(()->new IndexOutOfBoundsException("数组越界")) ;
    }

    public void loop(Consumer<Integer> before,Consumer<Integer> after){
        recursion(head,before,after);
    }
    /**
     * 递归遍历
     */
    private void recursion(Node  node, Consumer<Integer> before,Consumer<Integer> after){
        if (node == null){
            return;
        }
        before.accept(node.value);
        recursion(node.next,before,after);
        after.accept(node.value);
    }
}
